Be careful about disposing tools. The CRM registers resource files so that if your app uses the same tool twice, there is only one file open. But, if your applications abnormally quits (or the app doesn't close all of the files, the file is still registered, and therefore havoc may occur if you launch another CTB program.
Comm Toolbox Utilities ••••••••••••••••••••••••
Using the Popup CDEF
The minimum width for the popup title area is 1 pixel (this will draw no title at all. Specifying 0 will result in the left edge of the popup frame being cut off.
To use multiple controls that use the same menu, the application will manually have to perform a GetMenu, InsertMenu(hMenu, -1) before the first GetControl. When all controls are disposed of, the application will need to perform a DeleteMenu, DisposeMenu.
Writing Applications •••••••••••••••••••••••••
Opening/Saving Documents
To save a tool's configuration you can either call xxGetConfig() and save the config string, or get the config ptr from the manager record and save that.
To re-open the doc, call xxSetConfig() with the saved string or blockmove the saved config ptr back in and call xxValidate() to verify the configuration. (The problem with the latter is that it disregards the manual warning).
For the size parameter to blockmove, use GetPtrSize(hXXXX^^.config) instead of the size of the saved config block.
Since the document may contain a cache full of text, and it would be cool to be able to edit it from a standard text editor, we suggest you use the resource fork of the doc for the settings.
Alerts
To supress tools putting up alerts, use the xxQuiet bit. (The tool will still return the error code, though).
xxQuiet also supresses status dialogs, so if the app wants a status and does not want the alerts, the app will have to handle the status itself.
Cursors
If the terminal tool's cursor is not blinking:
- Make sure you call TMActivate() for all (de)activate events.
- Make sure you SetPort() to the right window before calling TMIdle().
Writing Tools •••••••••••••••••••••••••••
Tool Resources:
Tools are opened read-only (since they are sharable, they can't be modified since someone else may have a copy of the resource map.
To get resources (such as PICTs) from your tool you should do the following:
• and use CRMReleaseResource when you are done with a resources.
the CRMresource manager calls provide a mechanism for multiple
instantiations of a given tool to share resources and keep track of
the useCount of a given resource.
If you need to make a Mac toolbox call that uses some of your resources, such as GetNewDialog(), you must use the system res file as it will also be getting resources from the system (i.e. WDEF) and the tool is just below the system file.
cur := CurResFile;
UseResFile(0); { set to system res file }
GetNewDialog();
UseResFile(cur);
Type and creators:
Connection Tools cbnd
Terminal Tools tbnd
File Xfer Tools fbnd
You can specify your own icon, creator ID, etc.
Saving and Restoring configurations
Save the configuration string (better)
Save the configuration record (not so good)
Be prepared for the configuration record to change size (if different versions of the tool). It may grow OR shrink.
// PSEUDO CODE HERE
resH := Get1Resource('Tfig',1); { set the saved configs }
HLock(resH);
if (theTerm <> nil) then
begin
theSize := GetPtrSize(theTerm^^.config);
BlockMove(resH^,theTerm^^.config,theSize);
if TMValidate(theTerm) then { we had to update something }
BEGIN
SetHandleSize(resH, theSize);
BlockMove(theTerm^^.config, resH^, theSize); { so update the resource }
END;
end;
HUnlock(resH);
ReleaseResource(resH);
Terminal Tools •••••••••••••••••••••••••••
Connection Tools ••••••••••••••••••••••••••
ErrCodes:
Tools should set the errCode field in the ConnRecord EVERY time the tool is called. The best thing to do is set it to noErr right before it distributes the tool messages and to set it to the appropriate error code after the tool message is processed.
The tool also needs to set the errCode field prior to calling an asynchronous completion routine.
Alerts:
When something goes wrong, it is the tool's responsibility to inform the user (since it knows exactly what happened) and return the correct error code. If the xxQuiet bit has been set by the application, then the tool should not alert the user, but simply return the error code.
Bits:
statusDataAvailable: should be set whenever there's data, and cleared when there's not any.
Async Calls:
Note: the completor record is a data structure on the stack, not a pointer to something on the heap. Therefore, it goes away after your call completes. Make a copy of the relavent information.
If your tool supports multiple outstanding IO's, you need to block when you are executing (i.e. disable interrupts) the completion routine so that the errCode field doesn't get trounced upon.
Remember to lock the connection record if you are doing async IO and stuff.
Completion routines
May be called with interrupts disabled. Also, the connection handle should always be valid. If it isn't, you are in major trouble anyways and as such you can generally assume that you will get a valid connection handle in your completion routine.
Timeouts
A Timeout of 0 for reads and writes is a polling operation.
Supporting Channels
The tool is asked at CMNew time for a set of channels - cmData, cmAttn, and cmCntl.
The tool will clear those bits that it does not support. If none of these bits are set, the tool will pick its "default" channel(s).
Closing a Connection
If the connection is closed with outstanding IO, the completion routinesfor all of the IO's should be called.
cmInitMsg
Tools allocate IO buffers here. They are urged to use the buffer array provided in the connection record.
cmDisposeMsg
DO NOT DISPOSE OF THE config or oldConfig fields. The connection manager does this.
File Transfer Tools •••••••••••••••••••••••••
ErrCodes
Tools should set the errCode field in the ConnRecord EVERY time the tool is called. The best thing to do is set it to noErr right before it distributes the tool messages.
Alerts:
When something goes wrong, it is the tool's responsibility to inform the user (since it knows exactly what happened) and return the correct error code. If the xxQuiet bit has been set by the application, then the tool should not alert the user, but simply return the error code.